package com.jie.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.jie.common.constant.StrConst;
import com.jie.common.util.BaseParameterHolder;
import com.jie.component.id.toolkit.SnowflakeIdGenerator;
import com.jie.gateway.service.ApiRestrictService;
import com.jie.gateway.service.TokenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import static com.jie.common.constant.StrConst.*;

/**
 * @author jie
 * @version 1.0 2025-02-16
 */
@RequiredArgsConstructor
@Slf4j
@Component
public class RequestValidationFilter implements GlobalFilter, Ordered {

    private final SnowflakeIdGenerator idGenerator;

    private final ApiRestrictService apiRestrictService;

    private final TokenService tokenService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            ServerHttpRequest request = exchange.getRequest();
            // 链路调用id
            String traceId = request.getHeaders().getFirst(StrConst.TRACE_ID);
            if (StrUtil.isBlank(traceId)) {
                // 如果没有链路id，生成一个
                traceId = String.valueOf(idGenerator.nextId());
            }
            // 灰度参数
            String gray = request.getHeaders().getFirst(StrConst.GRAY_PARAMETER);
            // 设置日志追踪ID
            MDC.put(StrConst.TRACE_ID, traceId);
            // token
            String token = request.getHeaders().getFirst(StrConst.TOKEN);
            // 请求路径
            String url = request.getPath().value();
            // 设置基础参数到ThreadLocal
            BaseParameterHolder.setParameter(StrConst.TRACE_ID, traceId);
            BaseParameterHolder.setParameter(StrConst.GRAY_PARAMETER, gray);
            // 登录校验
            tokenService.doLoginVerify(token, url);
            // 请求限流
            apiRestrictService.doApiRestrict(url, request);
            // 装饰请求头
            ServerHttpRequest.Builder mutate = request.mutate()
                    .header(StrConst.TRACE_ID, traceId)
                    .header(StrConst.GRAY_PARAMETER, gray);
            if (StrUtil.isNotBlank(BaseParameterHolder.getParameter(StrConst.USER_ID))) {
                mutate.header(StrConst.USER_ID, BaseParameterHolder.getParameter(StrConst.USER_ID));
            }
            ServerHttpRequest newRequest = mutate.build();
            return chain.filter(exchange.mutate().request(newRequest).build());
        } finally {
            BaseParameterHolder.removeParameter(TRACE_ID);
            MDC.remove(TRACE_ID);
            BaseParameterHolder.removeParameter(GRAY_PARAMETER);
            BaseParameterHolder.removeParameter(USER_ID);
        }
    }


    @Override
    public int getOrder() {
        return -2;
    }
}
